<template>
  <div class="dialog-box">
    <div class="response" v-html="htmlContentRendered" ref="response"></div>
  </div>
</template>

<script>
import hljs from "highlight.js";
import "highlight.js/styles/github-dark.css";
import MarkdownIt from "markdown-it";
export default {
  props: ["content", "isQuestioning"],
  data() {
    return {
      md: null,
      htmlContent: "",
      typeIndex: 0,
      speed: 50,
      isAddCopyCodeEvent: true,
    };
  },
  watch: {
    content: {
      handler(val) {
        if (val.length > 0) {
          this.typeWriter();
        }
      },
    },
  },
  computed: {
    htmlContentRendered() {
      return this.md.render(this.htmlContent);
    },
  },
  methods: {
    handleCodeHighlightInit() {
      this.md = new MarkdownIt();
      this.md.set({
        highlight: (str, lang) => {
          let preCode = str;
          preCode =
            lang && hljs.getLanguage(lang)
              ? hljs.highlight(lang, str).value
              : hljs.highlightAuto(str).value;

          const lines = preCode
            .split("\n")
            .filter((line) => line.trim().length > 0);
          let codeHeader = this.createCodeHeader(lang);
          let html =
            codeHeader.outerHTML +
            `<div class="code">${lines.join("\n")}</div>`;
          return `<pre class="hljs"><code data-lang="${
            lang ? lang : "text"
          }">${html}</code></pre>`;
        },
      });
    },
    typeWriter() {
      if (this.typeIndex < this.content.length) {
        this.htmlContent += this.content.charAt(this.typeIndex);
        this.typeIndex++;

        this.$refs.response.scrollIntoView({
          block: "end",
        });

        setTimeout(this.typeWriter, this.speed);
      } else {
        this.addCopyCodeEvent();
      }
    },
    createCodeHeader(lang) {
      let codeHeader = document.createElement("div");
      codeHeader.classList.add("code-header");
      let langSpan = document.createElement("span");
      langSpan.classList.add("lang");
      langSpan.innerText = lang || "未知语言";
      let copyCodeBtn = document.createElement("button");
      copyCodeBtn.classList.add("copy-code");
      copyCodeBtn.innerText = "复制代码";
      codeHeader.appendChild(langSpan);
      codeHeader.appendChild(copyCodeBtn);

      return codeHeader;
    },
    addCopyCodeEvent() {
      this.$nextTick(() => {
        document.querySelectorAll(".dialog-box").forEach((dialogBox) => {
          dialogBox.addEventListener("click", (e) => {
            if (e.target.classList.contains("copy-code")) {
              const codeElement = e.target
                .closest(".hljs")
                .querySelector("code .code");

              const codeText = codeElement.innerText;
              navigator.clipboard.writeText(codeText).then(() => {
                e.target.innerText = "复制成功";
                setTimeout(() => {
                  e.target.innerText = "复制代码";
                }, 2000);
              });
            }
          });
        });
      });
    },
  },
  created() {
    this.handleCodeHighlightInit();
    // 非提问模式下，直接渲染内容
    if (!this.isQuestioning && this.content.length > 0) {
      this.htmlContent = this.content;
      this.addCopyCodeEvent();
    }
  },
};
</script>

<style scoped>
.response {
  margin-top: 0.5em;
  max-width: 700px;
  word-wrap: break-word;
}
</style>
